package com.control.back.halo.manage.service.impl;

import static java.util.stream.Collectors.toList;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.control.back.halo.basic.dao.IBaseDao;
import com.control.back.halo.basic.entity.vo.TreeNode;
import com.control.back.halo.basic.service.impl.BaseServiceImpl;
import com.control.back.halo.manage.dao.IFunctionDao;
import com.control.back.halo.manage.entity.Function;
import com.control.back.halo.manage.service.IFunctionService;

@Service
public class FunctionServiceImpl extends BaseServiceImpl<Function, Long> implements IFunctionService {

    @Autowired
    private IFunctionDao functionDao;

    @Override
    public IBaseDao<Function, Long> getBaseDao() {
        return this.functionDao;
    }

    @Override
    public Integer maxFunctionLevel(Integer type, Long parentId) {
        if (parentId == null || parentId <= 0) {
            return functionDao.maxFunctionLevel(type);
        } else {
            return functionDao.maxFunctionLevel(parentId);
        }
    }

    @Override
    public Function save(Function entity) {
        if (entity.getId() == null) {
            Integer level = 0;
            if (entity.getParent() != null && entity.getParent().getId() != null) {
                level = functionDao.maxFunctionLevel(entity.getParent().getId());
                entity.setParent(find(entity.getParent().getId()));
            } else {
                level = functionDao.maxFunctionLevel(entity.getType());
                entity.setParent(null);
            }
            level = (level == null ? 0 : level) + 1;
            entity.setLevel(level);
            entity.setActive(true);
        } else {
            Function entityFunction = find(entity.getId());
            entityFunction.setName(entity.getName());
            entityFunction.setUrl(entity.getUrl());
            entityFunction.setShiroPermission(entity.getShiroPermission());
            entity = entityFunction;
        }
        return super.save(entity);
    }

    private TreeNode toFunction(Function f){
        TreeNode node = new TreeNode();
        node.setId(f.getId());
        if (f.getParent() == null) {
            node.setPid(-1L);
        } else {
            node.setPid(f.getParent().getId());
        }
        node.setName(f.getName());
        if (f.getChild() != null) {
            node.setParent(true);
        }

        return node;
    }

    @Override
    public List<TreeNode> loadTree() {
        List<TreeNode> tnArray = findAll().stream().map(f -> toFunction(f)).collect(toList());
        return tnArray;
    }

    @Override
    public Map<String, Set<Function>> loadFunctionByAdminId(Long adminId) {
        Set<Function> funs = functionDao.loadFunctionByAdminId(adminId);
        Map<String, Set<Function>> mapfuns = new HashMap<>();

        funs.forEach(function -> {
            String id = "0";
            if (function.getParent() != null) {
                id = function.getParent().getId().toString();
            }

            if (mapfuns.get(id) != null) {
                mapfuns.get(id).add(function);
            } else {
                Set<Function> tops = new HashSet<>();
                tops.add(function);
                mapfuns.put(id, tops);
            }
        });

        return mapfuns;
    }

    @Override
    public Function findByLink(String linkAddress) {
        return functionDao.findByUrl(linkAddress);
    }

}
